package com.fulihui.wgj.service.user;

import com.alibaba.dubbo.config.annotation.Service;
import com.fulihui.common.builder.rpc.RpcResultBuilder;
import com.fulihui.common.conv.BeanConv;
import com.fulihui.common.error.Errors;
import com.fulihui.common.error.InvokeServiceException;
import com.fulihui.common.result.rpc.BaseResult;
import com.fulihui.common.util.ConditionValidator;
import com.fulihui.common.util.PasswordUtil;
import com.fulihui.wgj.dal.mybatis.domain.UserLogin;
import com.fulihui.wgj.dal.mybatis.mapper.UserLoginMapper;
import com.fulihui.wgj.dal.mybatis.repository.UserLoginRepository;
import com.fulihui.wgj.facade.dto.UserLoginDTO;
import com.fulihui.wgj.facade.request.user.UserLoginPasswordRequest;
import com.fulihui.wgj.facade.request.user.UserLoginRequest;
import com.fulihui.wgj.facade.request.user.UserPageRequest;
import com.fulihui.wgj.facade.result.user.UserPageResult;
import com.fulihui.wgj.facade.service.user.UserLoginService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * @author wang_wx
 * @date 2018-06-14
 */
@Component
@Service(interfaceClass = UserLoginService.class, version = "1.0.0")
public class UserLoginServiceImpl implements UserLoginService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserLoginServiceImpl.class);

    @Resource
    UserLoginMapper userLoginMapper;

    @Autowired
    UserLoginRepository userLoginRepository;

    @Override
    public UserPageResult queryPage(UserPageRequest userPageRequest) throws InvokeServiceException {
        String loginId = userPageRequest.getLoginId();
        int page = userPageRequest.getPage();
        int rows = userPageRequest.getRows();
        Example example = new Example(UserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(loginId)) {
            criteria.andLike("loginId", "%" + loginId + "%");

        }
        example.orderBy("gmtModified").desc();
        PageHelper.startPage(page, rows);
        List<UserLogin> userLoginList = userLoginMapper.selectByExample(example);
        PageInfo<UserLogin> userLoginPageInfo = new PageInfo<>(userLoginList);
        long total = userLoginPageInfo.getTotal();
        UserPageResult userPageResult = RpcResultBuilder.succPageResult(UserPageResult.class, userLoginPageInfo.getPageNum(), userLoginPageInfo.getPageSize(), (int) total);
        if (total > 0) {
            userPageResult.setValues(BeanConv.copy(userLoginPageInfo.getList(), UserLoginDTO.class));
        }
        return userPageResult;
    }

    @Override
    public BaseResult register(UserLoginRequest userLoginFormRequest) throws InvokeServiceException {
        ConditionValidator.validate(userLoginFormRequest);
        String loginId = userLoginFormRequest.getLoginId();
        UserLogin oldUser = selectUserByLoginId(loginId);
        if (Objects.nonNull(oldUser)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_ALREADY_EXISTS);
        }
        String password = userLoginFormRequest.getPassword();
        String salt = RandomStringUtils.randomAlphanumeric(16);
        String encryptPassword = PasswordUtil.encryptPassword(loginId, password, salt);
        UserLogin userLogin = new UserLogin();
        userLogin.setLoginId(loginId);
        userLogin.setPassword(encryptPassword);
        userLogin.setSalt(salt);
        int insertCount = userLoginMapper.insertSelective(userLogin);
        return insertCount > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.UserLoginError.USER_REGISTRATION_FAILED);
    }

    @Override
    public BaseResult updatePassword(UserLoginPasswordRequest updatePasswordRequest) throws InvokeServiceException {
        ConditionValidator.validate(updatePasswordRequest);
        String loginId = updatePasswordRequest.getLoginId();
        String oldPassword = updatePasswordRequest.getOldPassword();
        String newPassword = updatePasswordRequest.getNewPassword();
        UserLogin oldUser = selectUserByLoginId(loginId);
        if (Objects.isNull(oldUser)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
        }
        String salt = oldUser.getSalt();
        if (!PasswordUtil.passwordsMatch(loginId,
                oldPassword,
                salt,
                oldUser.getPassword())) {
            return RpcResultBuilder.fail(Errors.UserLoginError.OLD_PASSWORD_INCORRECTLY);
        }
        if (StringUtils.equals(oldPassword, newPassword)) {
            return RpcResultBuilder.fail(Errors.UserLoginError.NEWPASSWORD_SAME_AS_OLDPASSWORD);
        }
        String newEncryptPassword = PasswordUtil.encryptPassword(oldUser.getLoginId(), newPassword, salt);
        oldUser.setPassword(newEncryptPassword);
        int update = userLoginMapper.updateByPrimaryKeySelective(oldUser);
        return update > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.UserLoginError.CHANGE_PASSWORD_FAILED);
    }

    @Override
    public BaseResult login(UserLoginRequest userLoginFormRequest) throws InvokeServiceException {
        ConditionValidator.validate(userLoginFormRequest);
        String loginId = userLoginFormRequest.getLoginId();
        String password = userLoginFormRequest.getPassword();
        UserLogin userLogin = selectUserByLoginId(loginId);
        if (Objects.isNull(userLogin)) {
            return RpcResultBuilder.fail(Errors.Commons.RECORD_NOT_EXISTS);
        }
        if (PasswordUtil.passwordsMatch(loginId,
                password,
                userLogin.getSalt(),
                userLogin.getPassword())) {
            return RpcResultBuilder.succ();
        }
        return RpcResultBuilder.fail(Errors.UserLoginError.USER_AND_PASSWORD_NOT_MATCH);
    }

    @Override

    public BaseResult bindUserWxPlatform(String loginId, List<String> appIds) {
        int count = 0;
        try {
            count = userLoginRepository.bindUserWxPlatform(loginId, appIds);
        } catch (Exception e) {
            LOGGER.error(Errors.UserLoginWxError.BIND_FAILED.getErrmsg() + e);
        }
        LOGGER.info("rpc bindUserWxPlatform count = {}", count);
        return count > 0 ? RpcResultBuilder.succ() : RpcResultBuilder.fail(Errors.UserLoginWxError.BIND_FAILED);
    }

    /**
     * 根据登陆账号查询单个用户
     *
     * @param loginId
     * @return
     */
    private UserLogin selectUserByLoginId(String loginId) {
        Example example = new Example(UserLogin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("loginId", loginId);
        UserLogin userLogin = userLoginMapper.selectOneByExample(example);
        return userLogin;
    }
}
